<?php

namespace app\common\service\third_party_api;

use Yansongda\Pay\Pay;
use app\common\model\order\ShipOrder;
use app\common\model\order\Order;
use app\common\model\order\GoodsOrder;
use app\common\model\order\PayLog;
use app\common\model\order\HotelOrder;
use app\common\model\goods\Goods;
use app\common\service\Util;
use app\common\service\third_party_api\ShipApiService;
use think\facade\Db;
use think\facade\Log;
use think\facade\Request;


class PayApiService
{
    public function __construct()
    {
        $config = [
            'alipay' => [
                'default' => [
                    // 「必填」支付宝分配的 app_id
                    'app_id' => '2016082000295641',
                    // 「必填」应用私钥 字符串或路径
                    // 在 https://open.alipay.com/develop/manage 《应用详情->开发设置->接口加签方式》中设置
                    'app_secret_cert' => 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDRjOg5DnX+8L+rB8d2MbrQ30Z7JPM4hiDhawHSwQCQ7RlmQNpl6b/N6IrPLcPFC1uii179U5Il5xTZynfjkUyJjnHusqnmHskftLJDKkmGbSUFMAlOv+NlpUWMJ2A+VUopl+9FLyqcV+XgbaWizxU3LsTtt64v89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhDkFPxeBxHbfwppsul+DYUyTCcl0Ltbga/mUechk5BksW6yPPwprYHQBXyM16Jc3q5HbNxh3660FyvUBFLuVWIBs6RtR2gZCa6b8rOtCkPQKhUKvzRMlgheOowXsWdk99GjxGQDK5W4XAgMBAAECggEAYPKnjlr+nRPBnnNfR5ugzH67FToyrU0M7ZT6xygPfdyijaXDb2ggXLupeGUOjIRKSSijDrjLZ7EQMkguFHvtfmvcoDTDFaL2zq0a3oALK6gwRGxOuzAnK1naINkmeOmqiqrUab+21emEv098mRGbLNEXGCgltCtz7SiRdo/pgIPZ1wHj4MH0b0K2bFG3xwr51EyaLXKYH4j6w9YAXXsTdvzcJ+eRE0Yq4uGPfkziqg8d0xXSEt90HmCGHKo4O2eh1w1IlBcHfK0F6vkeUAtrtAV01MU2bNoRU147vKFxjDOVBlY1nIZY/drsbiPMuAfSsodL0hJxGSYivbKTX4CWgQKBgQDd0MkF5AIPPdFC+fhWdNclePRw4gUkBwPTIUljMP4o+MhJNrHp0sEy0sr1mzYsOT4J20hsbw/qTnMKGdgy784bySf6/CC7lv2hHp0wyS3Es0DRJuN+aTyyONOKGvQqd8gvuQtuYJy+hkIoHygjvC3TKndX1v66f9vCr/7TS0QPywKBgQCXgVHERHP+CarSAEDG6bzI878/5yqyJVlUeVMG5OXdlwCl0GAAl4mDvfqweUawSVFE7qiSqy3Eaok8KHkYcoRlQmAefHg/C8t2PNFfNrANDdDB99f7UhqhXTdBA6DPyW02eKIaBcXjZ7jEXZzA41a/zxZydKgHvz4pUq1BdbU5ZQKBgHyqGCDgaavpQVAUL1df6X8dALzkuqDp9GNXxOgjo+ShFefX/pv8oCqRQBJTflnSfiSKAqU2skosdwlJRzIxhrQlFPxBcaAcl0VTcGL33mo7mIU0Bw2H1d4QhAuNZIbttSvlIyCQ2edWi54DDMswusyAhHxwz88/huJfiad1GLaLAoGASIweMVNuD5lleMWyPw2x3rAJRnpVUZTc37xw6340LBWgs8XCEsZ9jN4t6s9H8CZLiiyWABWEBufU6z+eLPy5NRvBlxeXJOlq9iVNRMCVMMsKybb6b1fzdI2EZdds69LSPyEozjkxdyE1sqH468xwv8xUPV5rD7qd83+pgwzwSJkCgYBrRV0OZmicfVJ7RqbWyneBG03r7ziA0WTcLdRWDnOujQ9orhrkm+EY2evhLEkkF6TOYv4QFBGSHfGJ0SwD7ghbCQC/8oBvNvuQiPWI8B+00LwyxXNrkFOxy7UfIUdUmLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==',
                    // 「必填」应用公钥证书 路径
                    // 设置应用私钥后，即可下载得到以下3个证书
                    'app_public_cert_path' => '/Users/yansongda/pay/cert/appCertPublicKey_2016082000295641.crt',
                    // 「必填」支付宝公钥证书 路径
                    'alipay_public_cert_path' => '/Users/yansongda/pay/cert/alipayCertPublicKey_RSA2.crt',
                    // 「必填」支付宝根证书 路径
                    'alipay_root_cert_path' => '/Users/yansongda/pay/cert/alipayRootCert.crt',
                    'return_url' => 'https://yansongda.cn/alipay/return',
                    'notify_url' => 'https://yansongda.cn/alipay/notify',
                    // 「选填」第三方应用授权token
                    'app_auth_token' => '',
                    // 「选填」服务商模式下的服务商 id，当 mode 为 Pay::MODE_SERVICE 时使用该参数
                    'service_provider_id' => '',
                    // 「选填」默认为正常模式。可选为： MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
            'wechat' => [
                'default' => [
                    // 「必填」商户号，服务商模式下为服务商商户号
                    // 可在 https://pay.weixin.qq.com/ 账户中心->商户信息 查看
                    'mch_id' => env('mp_mch_id'),
                    // 「选填」v2商户私钥
                    'mch_secret_key_v2' => '',
                    // 「必填」v3 商户秘钥
                    // 即 API v3 密钥(32字节，形如md5值)，可在 账户中心->API安全 中设置
                    'mch_secret_key' => env('mp_mch_secret'),
                    // 「必填」商户私钥 字符串或路径
                    // 即 API证书 PRIVATE KEY，可在 账户中心->API安全->申请API证书 里获得
                    // 文件名形如：apiclient_key.pem
                    'mch_secret_cert' => '',
                    // 「必填」商户公钥证书路径
                    // 即 API证书 CERTIFICATE，可在 账户中心->API安全->申请API证书 里获得
                    // 文件名形如：apiclient_cert.pem
                    'mch_public_cert_path' => '',
                    // 「必填」微信回调url
                    // 不能有参数，如?号，空格等，否则会无法正确回调
                    'notify_url' => Request::domain() . '/index/user/wechatNotify',
                    // 「选填」公众号 的 app_id
                    // 可在 mp.weixin.qq.com 设置与开发->基本配置->开发者ID(AppID) 查看
                    'mp_app_id' => env('mp_app_id'),
                    // 「选填」小程序 的 app_id
                    'mini_app_id' => '',
                    // 「选填」app 的 app_id
                    'app_id' => '',
                    // 「选填」服务商模式下，子公众号 的 app_id
                    'sub_mp_app_id' => '',
                    // 「选填」服务商模式下，子 app 的 app_id
                    'sub_app_id' => '',
                    // 「选填」服务商模式下，子小程序 的 app_id
                    'sub_mini_app_id' => '',
                    // 「选填」服务商模式下，子商户id
                    'sub_mch_id' => '',
                    // 「选填」（适用于 2024-11 及之前开通微信支付的老商户）微信支付平台证书序列号及证书路径，强烈建议 php-fpm 模式下配置此参数
                    // 「必填」微信支付公钥ID及证书路径，key 填写形如 PUB_KEY_ID_0000000000000024101100397200000006 的公钥id，见 https://pay.weixin.qq.com/doc/v3/merchant/4013053249
                    'wechat_public_cert_path' => [
                        '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__ . '/Cert/wechatPublicKey.crt',
                        'PUB_KEY_ID_0000000000000024101100397200000006' => __DIR__ . '/Cert/publickey.pem',
                    ],
                    // 「选填」默认为正常模式。可选为： MODE_NORMAL, MODE_SERVICE
                    'mode' => Pay::MODE_NORMAL,
                ]
            ],
            // 'unipay' => [
            //     'default' => [
            //         // 「必填」商户号
            //         'mch_id' => '777290058167151',
            //         // 「选填」商户密钥：为银联条码支付综合前置平台配置：https://up.95516.com/open/openapi?code=unionpay
            //         'mch_secret_key' => '979da4cfccbae7923641daa5dd7047c2',
            //         // 「必填」商户公私钥
            //         'mch_cert_path' => __DIR__.'/Cert/unipayAppCert.pfx',
            //         // 「必填」商户公私钥密码
            //         'mch_cert_password' => '000000',
            //         // 「必填」银联公钥证书路径
            //         'unipay_public_cert_path' => __DIR__.'/Cert/unipayCertPublicKey.cer',
            //         // 「必填」
            //         'return_url' => 'https://yansongda.cn/unipay/return',
            //         // 「必填」
            //         'notify_url' => 'https://yansongda.cn/unipay/notify',
            //         'mode' => Pay::MODE_NORMAL,
            //     ],
            // ],
            // 'douyin' => [
            //     'default' => [
            //         // 「选填」商户号
            //         // 抖音开放平台 --> 应用详情 --> 支付信息 --> 产品管理 --> 商户号
            //         'mch_id' => '73744242495132490630',
            //         // 「必填」支付 Token，用于支付回调签名
            //         // 抖音开放平台 --> 应用详情 --> 支付信息 --> 支付设置 --> Token(令牌)
            //         'mch_secret_token' => 'douyin_mini_token',
            //         // 「必填」支付 SALT，用于支付签名
            //         // 抖音开放平台 --> 应用详情 --> 支付信息 --> 支付设置 --> SALT
            //         'mch_secret_salt' => 'oDxWDBr4U7FAAQ8hnGDm29i4A6pbTMDKme4WLLvA',
            //         // 「必填」小程序 app_id
            //         // 抖音开放平台 --> 应用详情 --> 支付信息 --> 支付设置 --> 小程序appid
            //         'mini_app_id' => 'tt226e54d3bd581bf801',
            //         // 「选填」抖音开放平台服务商id
            //         'thirdparty_id' => '',
            //         // 「选填」抖音支付回调地址
            //         'notify_url' => 'https://yansongda.cn/douyin/notify',
            //     ],
            // ],
            // 'jsb' => [
            //     'default' => [
            //         // 服务代码
            //         'svr_code' => '',
            //         // 「必填」合作商ID
            //         'partner_id' => '',
            //         // 「必填」公私钥对编号
            //         'public_key_code' => '00',
            //         // 「必填」商户私钥(加密签名)
            //         'mch_secret_cert_path' => '',
            //         // 「必填」商户公钥证书路径(提供江苏银行进行验证签名用)
            //         'mch_public_cert_path' => '',
            //         // 「必填」江苏银行的公钥(用于解密江苏银行返回的数据)
            //         'jsb_public_cert_path' => '',
            //         // 支付通知地址
            //         'notify_url' => '',
            //         // 「选填」默认为正常模式。可选为： MODE_NORMAL:正式环境, MODE_SANDBOX:测试环境
            //         'mode' => Pay::MODE_NORMAL,
            //     ],
            // ],
            'logger' => [
                'enable' => false,
                'file' => './logs/pay.log',
                'level' => 'debug', // 建议生产环境等级调整为 info，开发环境为 debug
                'type' => 'daily', // optional, 可选 daily.
                'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
            ],
            'http' => [ // optional
                'timeout' => 5.0,
                'connect_timeout' => 5.0,
                // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
            ],
        ];

        Pay::config($config);
    }

    // 支付部分------------------------------------------------------------------
    /**
     * 微信支付
     * @param int $type 1:船票订单 2:商城订单
     * @param int $id 订单ID
     * @param string $openid 微信用户openid
     */
    public function wxPay($type, $id, $openid)
    {
        $payAmount = 0;
        $outTradeNo = self::buildOutTradeNo();

        $order = self::preparePay($type, $id, $outTradeNo);

        $order = [
            'out_trade_no' => $outTradeNo,
            'description' => '订单,ID:' . $id,
            'amount' => [
                'total' => $payAmount,
            ],
            'payer' => [
                'openid' => $openid,
            ],
        ];
        $result = Pay::wechat()->mp($order);
        return $result;
    }

    /**
     * 支付宝支付
     * @param int $type 1:船票订单 2:商城订单
     * @param int $id 订单ID
     */
    public function aliPay($type, $id)
    {
        $payAmount = 0;
        $outTradeNo = self::buildOutTradeNo();

        $order = self::preparePay($type, $id, $outTradeNo);

        $order = [
            'out_trade_no' => $outTradeNo,
            'total_amount' => $payAmount,
            'subject' => '订单,ID:' . $id,
            'quit_url' => 'https://yansongda.cn',
        ];
        $result = Pay::alipay()->h5($order);
        return $result;
    }

    /**
     * 准备支付
     * @param int $type 1:船票订单 2:商城订单 4:商品订单
     * @param int $id 订单ID
     * @param string $outTradeNo 订单号
     * @return string
     */
    private static function preparePay($type, $id, $outTradeNo)
    {
        if ($type === 1) {
            $orderModel = new Order();
            $order = $orderModel->where('id', $id)->find();

            if (!$order) {
                return Util::ajaxReturn(0, '订单错误');
            }
            if ($order['status'] != Order::UN_PAID) {
                return Util::ajaxReturn(0, '订单不可支付');
            }
            $delayTime = time() - \app\common\model\order\ShipOrder::DELAY_TIME;
            if ($order['add_time'] < $delayTime) {
                return Util::ajaxReturn(0, '订单已超时');
            }
            $orderModel->where('id', $id)->update(['out_trade_no' => $outTradeNo]);

            $payAmount = floatval($order['total']) + floatval($order['charge']);
            $orders = Order::where('link_order_id', $id)->select();

            $childredCount = Db::name('ship_order_take_children')
                ->where('ship_order_id', $id)
                ->count();
            // 使用app_config表替代不存在的system表
            $childredCharges = Db::name('app_config')->where('name', 'ship_charges')->find();
            if ($childredCharges) {
                $payAmount += (floatval($childredCount) * $childredCharges['value']);
            }

            if ($orders) {
                Order::where('link_order_id', $id)->update(['out_trade_no' => $outTradeNo]);

                foreach ($orders as $order) {
                    $payAmount += floatval($order['order_money']);
                }
            }
        } elseif ($type === 2) {
            $order = Order::where('id', $id)->find();
            if (!$order) {
                return Util::ajaxReturn(0, '订单错误');
            }
            if ($order['status'] != Order::UN_PAID) {
                return Util::ajaxReturn(0, '订单不可支付');
            }
            $delayTime = time() - Order::DELAY_TIME;
            if ($order['add_time'] < $delayTime) {
                return Util::ajaxReturn(0, '订单已超时');
            }
            Order::where('id', $id)->update(['out_trade_no' => $outTradeNo]);
            $payAmount = floatval($order['order_money']);
        } elseif ($type === 4) {
            $goodsOrderModel = new GoodsOrder();
            $order = $goodsOrderModel->where('id', $id)->find();
            if (!$order) {
                return Util::ajaxReturn(0, '订单错误');
            }
            if ($order['status'] != GoodsOrder::STATUS_UN_PAID) {
                return Util::ajaxReturn(0, '订单不可支付');
            }
            $goodsOrderModel->where('id', $id)->update(['out_trade_no' => $outTradeNo]);
            $payAmount = floatval($order['pay_amount']);
        } else {
            return Util::ajaxReturn(0, '订单类型异常');
        }

        return $order;
    }

    // 支付部分END---------------------------------------------------------------
    // 回调部分------------------------------------------------------------------

    /**
     * 支付宝回调
     * @return void
     */
    public function aliCallback()
    {
        try {
            $alipay = Pay::alipay();
            $data = $alipay->verify();
            $this->notifySuccess(1, $data);

            return $alipay->success(); // 支付宝回调

        } catch (\Exception $e) {
            Log::debug('支付宝支付回调_Exception:' . $e->getMessage() . ' row: ' . $e->getLine());
        } catch (\Error $e) {
            Log::error('支付宝支付回调_Error:' . $e->getMessage() . ' row: ' . $e->getLine()); // 记录日志
        }
    }

    /**
     * 微信回调
     * @return void
     */
    public function wxCallback()
    {
        try {
            $wechat = Pay::wechat();
            $data = $wechat->verify();
            $this->notifySuccess(2, $data);

            return $wechat->success(); // 微信回调

        } catch (\Exception $e) {
            Log::debug('微信支付回调_Exception:' . $e->getMessage() . ' row: ' . $e->getLine());
        } catch (\Error $e) {
            Log::error('微信支付回调_Error:' . $e->getMessage() . ' row: ' . $e->getLine()); // 记录日志
        }
    }

    /**
     * 处理支付成功通知
     * @param string $type 支付类型（1：支付宝；2：微信）
     * @param array $message 支付通知数据
     * @return bool
     */
    private function notifySuccess($type, $message)
    {
        $order = Order::where('out_trade_no', $message['out_trade_no'])->find();

        if ($type == 1) {
            $tradeNo = $message['trade_no'];
            $totalAmount = $message['total_amount'];
        } elseif ($type == 2) {
            $tradeNo = $message['transaction_id'];
            $totalAmount = bcdiv($message['total_fee'], '100', 2);
        }

        //记录支付信息
        PayLog::insert([
            'order_sn' => isset($order['order_sn']) ? $order['order_sn'] : '--',
            'log_type' => 1,
            'pay_type' => $type,
            'out_trade_no' => isset($message['out_trade_no']) ? $message['out_trade_no'] : '--',
            'trade_no' => $tradeNo ? $tradeNo : '--',
            'total_amount' => isset($totalAmount) ? $totalAmount : '0.00',
            'pay_notify' => json_encode($message),
            'pay_time' => date('Y-m-d H:i:s'),
        ]);

        if (($type == 1 && $message['trade_status'] === 'TRADE_SUCCESS') || ($type == 2 && $message['result_code'] === 'SUCCESS')) {
            try {
                // 商品订单
                if ($order['order_type'] == 1) {
                    $goodsOrderModel = new GoodsOrder();
                    $goodsOrder = $goodsOrderModel->where('order_sn', $order['order_sn'])->find();
                    if ($goodsOrder['status'] == 1) {
                        $goodsOrderModel->where('id', $goodsOrder['id'])->update([
                            'status' => 2,
                        ]);

                        //产品销量
                        try {
                            $goodsModel = new \app\common\model\goods\Goods();
                            $goods = $goodsModel->where('id', $goodsOrder['goods_id'])->field('id,sale_num')->find();
                            $goodsSaleNum = 0;
                            if ($goods) {
                                $goodsSaleNum = intval($goods['sale_num']);
                            }
                            $goodsSaleNum += intval($goodsOrder['goods_num']);
                            $goodsModel->where('id', $goodsOrder['goods_id'])->update(['sale_num' => $goodsSaleNum]);
                        } catch (\Exception $e) {
                            Log::error('产品销量更新错误2:goods_id=' . $goodsOrder['goods_id'] . ',错误：' . $e->getMessage());
                        }
                    }
                    // 船票订单
                } elseif ($order['order_type'] == 2) {
                    $shipOrderModel = new ShipOrder();
                    $shipOrder = $shipOrderModel->where('order_sn', $order['order_sn'])->find();
                    if ($shipOrder['status'] == 1) {
                        $shipOrderModel->where('id', $shipOrder['id'])->update([
                            'status' => 2,
                        ]);
                        $shipOrder['contact_list'] = json_decode($shipOrder['contact_list'], true);
                        $shipOrder['chooseSeat'] = json_decode($shipOrder['chooseSeat'], true);
                        $shipOrder['chooseFlight'] = json_decode($shipOrder['chooseFlight'], true);
                        $shipOrder['shipline'] = json_decode($shipOrder['shipline'], true);
                        try {
                            //同程确认出票
                            $shipApiService = new ShipApiService();
                            $body_arr = [
                                'orderSerialId' => $shipOrder['tc_order_no'],        //同程订单流水号
                            ];
                            $shipApiService->confirmOrder($body_arr);
                        } catch (\Exception $e) {
                            Log::error(__FUNCTION__ . '出票api请求出错:' . $e->getMessage());
                        }
                    }
                    //上岛票
                    $goodsOrderModel = new GoodsOrder();
                    $goodsOrders = $goodsOrderModel->where('out_trade_no', $_POST['out_trade_no'])->select();
                    if (!empty($goodsOrders)) {
                        foreach ($goodsOrders as $order) {
                            if ($order && $order['status'] == 1) {
                                Db::name('order')->where('id', $order['id'])->update([
                                    'status' => 2,
                                    'pay_type' => 2,
                                    'pay_money' => $_POST['total_amount'],
                                    'pay_time' => time(),
                                    'pay_notify_data' => json_encode($_POST), // 修复字段名拼写错误
                                    'trade_no' => $_POST['trade_no']
                                ]);
                                //产品销量
                                try {
                                    $goods = Db::name('goods')->where('id', $order['goods_id'])->field('id,sale_num')->find();
                                    $goodsSaleNum = 0;
                                    if ($goods) {
                                        $goodsSaleNum = intval($goods['sale_num']);
                                    }
                                    $goodsSaleNum += intval($order['goods_num']);
                                    Db::name('goods')->where('id', $order['goods_id'])->update(['sale_num' => $goodsSaleNum]);
                                } catch (\Exception $e) {
                                    Log::error('产品销量更新错误1:goods_id=' . $order['goods_id'] . ',错误：' . $e->getMessage());
                                    continue;
                                }
                            }
                        }
                    }
                    // 酒店住宿类订单
                } elseif ($order['order_type'] == 3) {
                    $hotelOrder = HotelOrder::where('order_sn', $order['order_sn'])->find();
                    if ($hotelOrder['status'] == 1) {
                        Db::name('mall_order')->where('id', $hotelOrder['id'])->update([
                            'status' => HotelOrder::STATUS_UN_DELIVERY, //待发货
                            'trade_no' => $_POST['trade_no'],
                            'pay_amount' => $_POST['total_amount'],
                            'pay_time' => time(),
                            'pay_noitfy_data' => json_encode($_POST),
                            'pay_type' => 2
                        ]);
                        //产品销量
                        try {
                            $goodsList = Db::name('mall_order_goods')->where('order_id', $hotelOrder['id'])->field('id,goods_id,goods_num')->select();
                            foreach ($goodsList as $item) {
                                $goods = Db::name('mall_goods')->where('id', $item['goods_id'])->field('id,sale_num')->find();
                                $goodsSaleNum = 0;
                                if ($goods) {
                                    $goodsSaleNum = intval($goods['sale_num']);
                                }
                                $goodsSaleNum += intval($item['goods_num']);
                                Db::name('mall_goods')->where('id', $goods['id'])->update(['sale_num' => $goodsSaleNum]);
                            }
                        } catch (\Exception $e) {
                            Log::error('特产超市订单支付错误：' . $e->getMessage());
                        }
                    }
                } else {
                    echo 'fail';
                    die;
                }
            } catch (\Exception $e) {
                Log::debug('支付宝支付回调_Exception:' . $e->getMessage() . ' row: ' . $e->getLine());
            } catch (\Error $e) {
                Log::error('支付宝支付回调_Error:' . $e->getMessage() . ' row: ' . $e->getLine()); // 记录日志
            }
        }
    }

    // 支付回调部分END-------------------------------------------------------------
    // 退款部分START-------------------------------------------------------------
    /**
     * 微信退款
     * @param array $params 退款参数
     * @return array
     */
    public static function wxRefund(array $params)
    {
        return Pay::wechat()->refund($params);
    }

    /**
     * 支付宝退款
     * @param array $params 退款参数
     * @return array
     */
    public static function aliRefund(array $params)
    {
        // 使用支付插件进行支付宝退款
        return Pay::alipay()->refund($params);
    }

    // 退款部分END-------------------------------------------------------------

    /**
     * 构建支付订单号
     * @return string
     */
    public static function buildOutTradeNo()
    {
        $orderNo = date('YmdHis') . uniqid();
        return $orderNo;
    }

    /**
     * 支付回调
     * @param string $type 支付类型
     * @return void
     */
    public function callback($type)
    {
        return Pay::{$type}()->callback();
    }
}
